package co.gov.medellin.ssti.sub.model.service.ws.vivanto.client;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;

import org.springframework.stereotype.Component;

import co.gov.medellin.ssti.sub.model.service.ws.vivanto.artifacts.Consulta;
import co.gov.medellin.ssti.sub.model.service.ws.vivanto.artifacts.IConsulta;
import co.gov.medellin.ssti.sub.model.service.ws.vivanto.artifacts.ParametrosEntradaGrupoFamiliarIdentificador;
import co.gov.medellin.ssti.sub.model.service.ws.vivanto.artifacts.ParametrosEntradaGrupoFamiliarNRadicado;
import co.gov.medellin.ssti.sub.model.service.ws.vivanto.artifacts.ParametrosEntradaVictimaPorDocumento;
import co.gov.medellin.ssti.sub.model.service.ws.vivanto.artifacts.ParametrosSalidaVictima;
import co.gov.medellin.ssti.sub.model.service.ws.vivanto.artifacts.ResultadoConsulta;
import co.gov.medellin.ssti.sub.model.service.ws.vivanto.vo.VariablesSalidaDesc;

@Component
public class VivantoConsumer {
	private final int TIMEOUT = 30 * 60 * 1000;
	public static final String TIMEOUT_MSG = "Se ha agotado el tiempo de espera para obtener respuesta.";

	private static final String NAMESPACE_URI = "http://schemas.datacontract.org/2004/07/WcfConsultaEntidadesExternas.Common.DTO";
	private static final String TOKEN = "Token";
	private static final String NUMERO_DOCUMENTO = "NumeroDocumento";
	private static final String NUMERO_DE_RADICADO = "NumeroDeRadicado";

	public static final String CONSULTAR_VICTIMA = "CONSULTAR_VICTIMA";
	public static final String CONSULTA_GRUPO_FAMILIAR_IDENTIFICADOR = "CONSULTA_GRUPO_FAMILIAR_IDENTIFICADOR";
	public static final String CONSULTA_GRUPO_FAMILIAR_RADICADO = "CONSULTA_GRUPO_FAMILIAR_RADICADO";

	private final String VICTIMA418 = "VICTIMA418";
	private final String VICTIMARUV = "VICTIMARUV";
	private final String VICTIMASIPOD = "VICTIMASIPOD";
	private final String VICTIMASIRAV = "VICTIMASIRAV";

	private static final String TOKEN_KEY = "2CEC286E-07C1-4ABE-A096-97B772C0D950";

	private QName qNameToken;
	private JAXBElement<String> valToken;

	private QName qNameNumeroDocumento;

	private QName qNameNumeroDeRadicado;

	private ParametrosEntradaVictimaPorDocumento pEntradaVictimaPorDocumento = null;
	private ParametrosEntradaGrupoFamiliarIdentificador pEntradaGFIdentificador = null;
	private ParametrosEntradaGrupoFamiliarNRadicado pEntradaGFNRadicado = null;
	private ParametrosSalidaVictima salidaVictima = null;
	private ParametrosSalidaVictima salidaGrupoFamiliarIdentificador = null;
	private ParametrosSalidaVictima salidaGrupoFamiliarRadicado = null;

	private Consulta consulta;
	private IConsulta iConsulta;
	private boolean inicializado;

	private VariablesSalidaDesc variablesSalidaDesc;

	public VivantoConsumer(){
	}

	public void inicializar() throws IOException {
		Properties properties = new Properties();
		InputStream input = null;
		try {
			input = getClass()
					.getClassLoader()
					.getResourceAsStream(
							"co/gov/medellin/ssti/sub/common/properties/strings.properties");
			properties.load(input);

			// jaw-ws
			this.consulta = new Consulta();
			this.iConsulta = consulta.getBasicHttpBindingIConsulta();
			// set timeout
			((BindingProvider) iConsulta).getRequestContext().put(
					"com.sun.xml.ws.request.timeout", TIMEOUT);

			// Qualified Name Token
			qNameToken = new QName(NAMESPACE_URI, TOKEN);
			valToken = new JAXBElement<String>(qNameToken, String.class,
					TOKEN_KEY);

			// Qualified Name NumeroDocumento
			qNameNumeroDocumento = new QName(NAMESPACE_URI, NUMERO_DOCUMENTO);

			// Qualified Name NumeroDeRadicado
			qNameNumeroDeRadicado = new QName(NAMESPACE_URI, NUMERO_DE_RADICADO);

			variablesSalidaDesc = new VariablesSalidaDesc();
			variablesSalidaDesc.setDepartamentoDeclaracion(properties
					.getProperty("vivanto.departamentoDeclaracion.nombre"));
			variablesSalidaDesc.setDepartamentoSiniestro(properties
					.getProperty("vivanto.departamentoSiniestro.nombre"));
			variablesSalidaDesc.setEstadoValoracion(properties
					.getProperty("vivanto.estadoValoracion.nombre"));
			variablesSalidaDesc.setFechaDeclaracion(properties
					.getProperty("vivanto.fechaDeclaracion.nombre"));
			variablesSalidaDesc.setFechaSiniestro(properties
					.getProperty("vivanto.fechaSiniestro.nombre"));
			variablesSalidaDesc.setFechaValoracion(properties
					.getProperty("vivanto.fechaValoracion.nombre"));
			variablesSalidaDesc.setHechoVictimizante(properties
					.getProperty("vivanto.hechoVictimizante.nombre"));
			variablesSalidaDesc.setIdDeclaracion(properties
					.getProperty("vivanto.idDeclaracion.nombre"));
			variablesSalidaDesc.setMunicipioDeclaracion(properties
					.getProperty("vivanto.municipioDeclaracion.nombre"));
			variablesSalidaDesc.setMunicipioSiniestro(properties
					.getProperty("vivanto.municipioSiniestro.nombre"));
			variablesSalidaDesc.setNumeroDocumento(properties
					.getProperty("vivanto.numeroDocumento.nombre"));
			variablesSalidaDesc.setNumeroFUD(properties
					.getProperty("vivanto.numeroFUD.nombre"));
			variablesSalidaDesc.setPrimerApellido(properties
					.getProperty("vivanto.primerApellido.nombre"));
			variablesSalidaDesc.setPrimerNombre(properties
					.getProperty("vivanto.primerNombre.nombre"));
			variablesSalidaDesc.setRelacion(properties
					.getProperty("vivanto.relacion.nombre"));
			variablesSalidaDesc.setResponsable(properties
					.getProperty("vivanto.responsable.nombre"));
			variablesSalidaDesc.setSegundoApellido(properties
					.getProperty("vivanto.segundoApellido.nombre"));
			variablesSalidaDesc.setSegundoNombre(properties
					.getProperty("vivanto.segundoNombre.nombre"));
			variablesSalidaDesc.setTipoDesplazamiento(properties
					.getProperty("vivanto.tipoDesplazamiento.nombre"));
			variablesSalidaDesc.setTipoDocumento(properties
					.getProperty("vivanto.tipoDocumento.nombre"));
			variablesSalidaDesc.setTipoVictima(properties
					.getProperty("vivanto.tipoVictima.nombre"));
			inicializado = true;
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * Metodo que consume la operacion consultarVictima del WS de vivanto.
	 * 
	 * @param numeroDocumento
	 *            Numero de documento de la victima.
	 * @return
	 */
	public ParametrosSalidaVictima consultarVictima(String numeroDocumento)
			throws IOException {
		if (!inicializado) {
			this.inicializar();
		}

		JAXBElement<String> valNumeroDocumento = new JAXBElement<String>(
				qNameNumeroDocumento, String.class, numeroDocumento);

		// parametros de entrada para consultarVictima
		if (pEntradaVictimaPorDocumento == null) {
			pEntradaVictimaPorDocumento = new ParametrosEntradaVictimaPorDocumento();
		}
		pEntradaVictimaPorDocumento.setNumeroDocumento(valNumeroDocumento);
		pEntradaVictimaPorDocumento.setToken(valToken);

		salidaVictima = iConsulta.consultarVictima(pEntradaVictimaPorDocumento);
		return salidaVictima;
	}

	/**
	 * Metodo que consume la operacion consultaGrupoFamiliarRadicado del WS de
	 * vivanto.
	 * 
	 * @param numeroDeRadicado
	 *            Numero de radicado.
	 * @return
	 */
	public ParametrosSalidaVictima consultaGrupoFamiliarRadicado(
			String numeroDeRadicado) throws IOException {
		if (!inicializado) {
			this.inicializar();
		}

		JAXBElement<String> valNumeroDeRadicado = new JAXBElement<String>(
				qNameNumeroDeRadicado, String.class, numeroDeRadicado);

		// parametros de entrada para consultaGrupoFamiliarRadicado
		if (pEntradaGFNRadicado == null) {
			pEntradaGFNRadicado = new ParametrosEntradaGrupoFamiliarNRadicado();
		}
		pEntradaGFNRadicado.setNumeroDeRadicado(valNumeroDeRadicado);
		pEntradaGFNRadicado.setToken(valToken);

		salidaGrupoFamiliarRadicado = iConsulta
				.consultaGrupoFamiliarRadicado(pEntradaGFNRadicado);
		return salidaGrupoFamiliarRadicado;
	}

	/**
	 * Metodo que consume la operacion consultaGrupoFamiliarIdentificador del WS
	 * de vivanto.
	 * 
	 * @param numeroDocumento
	 *            El numero de documento de la victima.
	 * @return
	 */
	public ParametrosSalidaVictima consultaGrupoFamiliarIdentificador(
			String numeroDocumento) throws IOException {
		if (!inicializado) {
			this.inicializar();
		}

		JAXBElement<String> valNumeroDocumento = new JAXBElement<String>(
				qNameNumeroDocumento, String.class, numeroDocumento);

		// parametros de entrada para consultaGrupoFamiliarIdentificador
		if (pEntradaGFIdentificador == null) {
			pEntradaGFIdentificador = new ParametrosEntradaGrupoFamiliarIdentificador();
		}
		pEntradaGFIdentificador.setNumeroDocumento(valNumeroDocumento);
		pEntradaGFIdentificador.setToken(valToken);

		salidaGrupoFamiliarIdentificador = iConsulta
				.consultaGrupoFamiliarIdentificador(pEntradaGFIdentificador);
		return salidaGrupoFamiliarIdentificador;
	}

	/**
	 * Metodo que indica si en el objeto ParametrosSalidaVictima salidaVictima
	 * se tiene resultados de la fuente SIRAV, es decir esta registrado en SIRAV
	 * como victima.
	 * 
	 * @param salidaVictima
	 * @return
	 */
	public boolean esVictimaSirav(ParametrosSalidaVictima salidaVictima) {

		if (salidaVictima != null
				&& salidaVictima.getVictimaSIRAV() != null
				&& salidaVictima.getVictimaSIRAV().getValue() != null
				&& salidaVictima.getVictimaSIRAV().getValue()
						.getResultadoConsulta() != null
				&& !salidaVictima.getVictimaSIRAV().getValue()
						.getResultadoConsulta().isEmpty()) {
			return true;
		}

		return false;
	}

	/**
	 * Metodo que indica si en el objeto ParametrosSalidaVictima salidaVictima
	 * se tiene resultados de la fuente SIPOD, es decir esta registrado en SIPOD
	 * como victima.
	 * 
	 * @param salidaVictima
	 * @return
	 */
	public boolean esVictimaSipod(ParametrosSalidaVictima salidaVictima) {
		if (salidaVictima != null
				&& salidaVictima.getVictimaSIPOD() != null
				&& salidaVictima.getVictimaSIPOD().getValue() != null
				&& salidaVictima.getVictimaSIPOD().getValue()
						.getResultadoConsulta() != null
				&& !salidaVictima.getVictimaSIPOD().getValue()
						.getResultadoConsulta().isEmpty()) {
			return true;
		}
		return false;
	}

	/**
	 * Metodo que indica si en el objeto ParametrosSalidaVictima salidaVictima
	 * se tiene resultados de la fuente RUV, es decir esta registrado en RUV
	 * como victima.
	 * 
	 * @param salidaVictima
	 * @return
	 */
	public boolean esVictimaRuv(ParametrosSalidaVictima salidaVictima) {
		if (salidaVictima != null
				&& salidaVictima.getVictimaRUV() != null
				&& salidaVictima.getVictimaRUV().getValue() != null
				&& salidaVictima.getVictimaRUV().getValue()
						.getResultadoConsulta() != null
				&& !salidaVictima.getVictimaRUV().getValue()
						.getResultadoConsulta().isEmpty()) {
			return true;
		}
		return false;
	}

	/**
	 * Metodo que indica si en el objeto ParametrosSalidaVictima salidaVictima
	 * se tiene resultados de la fuente 418, es decir esta registrado en 418
	 * como victima.
	 * 
	 * @param salidaVictima
	 * @return
	 */
	public boolean esVictima418(ParametrosSalidaVictima salidaVictima) {
		if (salidaVictima != null
				&& salidaVictima.getVictima418() != null
				&& salidaVictima.getVictima418().getValue() != null
				&& salidaVictima.getVictima418().getValue()
						.getResultadoConsulta() != null
				&& !salidaVictima.getVictima418().getValue()
						.getResultadoConsulta().isEmpty()) {
			return true;
		}
		return false;
	}

	/**
	 * Metodo que retorna un string html sencillo para mostrar el contenido de
	 * la salida en una pagina.
	 * 
	 * @param salidaVictima
	 * @return
	 * @throws ServletException
	 */
	public String printSalidaHTML(ParametrosSalidaVictima salidaVictima)
			throws Exception {
		if (salidaVictima != null) {
			if (!salidaVictima.getMensajeError().getValue().equals("")) {
				throw new Exception(salidaVictima.getMensajeError().getValue());
			}
			StringBuffer sb = new StringBuffer();

			// victima 418
			if (esVictima418(salidaVictima)) {
				sb.append("<b>victima 418</b><br>");
				sb.append(printVariables(salidaVictima, VICTIMA418));
			}

			// victima RUV
			if (esVictimaRuv(salidaVictima)) {
				sb.append("<b>victima RUV</b><br>");
				sb.append(printVariables(salidaVictima, VICTIMARUV));
			}

			// victima SIPOD
			if (esVictimaSipod(salidaVictima)) {
				sb.append("<u>victima SIPOD</u><br>");
				sb.append(printVariables(salidaVictima, VICTIMASIPOD));
			}

			// victima SIRAV.
			if (esVictimaSirav(salidaVictima)) {
				sb.append("<b>victima SIRAV</b><br>");
				sb.append(printVariables(salidaVictima, VICTIMASIRAV));
			}
			return sb.toString();
		}
		return "";
	}

	private String printVariables(ParametrosSalidaVictima salidaVictima,
			String cualFuente) {
		final String B_OPEN = "<b>";
		final String B_CLOSE = "</b>";
		final String BR = "<br>";
		final String COLON = ": ";

		List<ResultadoConsulta> resultadoConsulta = null;

		if (VICTIMA418.equals(cualFuente)) {
			resultadoConsulta = salidaVictima.getVictima418().getValue()
					.getResultadoConsulta();
		} else if (VICTIMASIRAV.equals(cualFuente)) {
			resultadoConsulta = salidaVictima.getVictimaSIRAV().getValue()
					.getResultadoConsulta();
		} else if (VICTIMARUV.equals(cualFuente)) {
			resultadoConsulta = salidaVictima.getVictimaRUV().getValue()
					.getResultadoConsulta();
		} else if (VICTIMASIPOD.equals(cualFuente)) {
			resultadoConsulta = salidaVictima.getVictimaSIPOD().getValue()
					.getResultadoConsulta();
		}

		if (resultadoConsulta == null) {
			return "";
		}
		StringBuffer sb = new StringBuffer();
		for (ResultadoConsulta res : resultadoConsulta) {
			sb.append(B_OPEN + variablesSalidaDesc.getDepartamentoDeclaracion()
					+ B_CLOSE + COLON
					+ res.getDepartamentoDeclaracion().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getDepartamentoSiniestro()
					+ B_CLOSE + COLON
					+ res.getDepartamentoSiniestro().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getEstadoValoracion()
					+ B_CLOSE + COLON + res.getEstadoValoracion().getValue()
					+ BR);

			sb.append(B_OPEN + variablesSalidaDesc.getFechaDeclaracion()
					+ B_CLOSE + COLON + res.getFechaDeclaracion() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getFechaSiniestro()
					+ B_CLOSE + COLON + res.getFechaDeclaracion() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getFechaValoracion()
					+ B_CLOSE + COLON + res.getFechaValoracion() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getHechoVictimizante()
					+ B_CLOSE + COLON + res.getHechoVictimizante().getValue()
					+ BR);

			sb.append(B_OPEN + variablesSalidaDesc.getIdDeclaracion() + B_CLOSE
					+ COLON + res.getIdDeclaracion().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getMunicipioDeclaracion()
					+ B_CLOSE + COLON
					+ res.getMunicipioDeclaracion().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getMunicipioSiniestro()
					+ B_CLOSE + COLON + res.getMunicipioSiniestro().getValue()
					+ BR);

			sb.append(B_OPEN + variablesSalidaDesc.getNumeroDocumento()
					+ B_CLOSE + COLON + res.getNumeroDocumento().getValue()
					+ BR);

			sb.append(B_OPEN + variablesSalidaDesc.getNumeroFUD() + B_CLOSE
					+ COLON + res.getNumeroFUD().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getPrimerApellido()
					+ B_CLOSE + COLON + res.getPrimerApellido().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getPrimerNombre() + B_CLOSE
					+ COLON + res.getPrimerNombre().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getRelacion() + B_CLOSE
					+ COLON + res.getRelacion().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getResponsable() + B_CLOSE
					+ COLON + res.getResponsable().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getSegundoApellido()
					+ B_CLOSE + COLON + res.getSegundoApellido().getValue()
					+ BR);

			sb.append(B_OPEN + variablesSalidaDesc.getSegundoNombre() + B_CLOSE
					+ COLON + res.getSegundoNombre().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getTipoDesplazamiento()
					+ B_CLOSE + COLON + res.getTipoDesplazamiento().getValue()
					+ BR);

			sb.append(B_OPEN + variablesSalidaDesc.getTipoDocumento() + B_CLOSE
					+ COLON + res.getTipoDocumento().getValue() + BR);

			sb.append(B_OPEN + variablesSalidaDesc.getTipoVictima() + B_CLOSE
					+ COLON + res.getTipoVictima().getValue() + BR);
			sb.append(BR);

		}
		return sb.toString();
	}
}
